#include "LightDimmer.h"

#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app-common/zap-generated/callback.h>

using namespace app::Clusters;
using namespace app::Clusters::LevelControl;
using namespace app::Clusters::LevelControl::Attributes;

namespace {
constexpr uint16_t kLevelClusterRevision = 1u;
constexpr DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(levelAttrs)
    DECLARE_DYNAMIC_ATTRIBUTE(Attributes::CurrentLevel::Id, INT8U, 1, 0),
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();

constexpr CommandId levelIncomingCommands[] = {
        Commands::MoveToLevel::Id,
        Commands::Move::Id,
        Commands::Step::Id,
        Commands::Stop::Id,
        Commands::MoveToLevelWithOnOff::Id,
        Commands::MoveWithOnOff::Id,
        Commands::StepWithOnOff::Id,
        Commands::StopWithOnOff::Id,
        kInvalidCommandId,
    };

EmberAfCluster levelControlClusters = DECLARE_DYNAMIC_CLUSTER(LevelControl::Id, levelAttrs,
                                                              ZAP_CLUSTER_MASK(SERVER), levelIncomingCommands, nullptr);
}

LightDimmer::LightDimmer(const ::BasicInformation* node)
    : LightOnOff(node) {
    ChipLogProgress(DeviceLayer, "LightOnOff");
    mClusters.push_back(levelControlClusters);
    mLevel = static_cast<uint8_t>(80 * 255 / 100);
}

void LightDimmer::UpdateLevel(uint8_t level) {
    if (mLevel == level) {
        return;
    }
    mLevel = level;
    ChipLogProgress(DeviceLayer, "Device[%s]: UpdateLevel=%d%%", GetName().c_str(), mLevel);
    NotifyStatusChanged(Id, CurrentLevel::Id);
}


void LightDimmer::SetLevel(uint8_t level) {
    if (IsOn() && level != 0) {
        auto block = DataBlock(Path(Id, CurrentLevel::Id), level);
        SendMessage(&block);
    }
    // 立马上报一个状态给app，草坪灯会延时上报
    UpdateLevel(level);
}

uint8_t LightDimmer::GetLevel() const {
    if (mLevel == 0xff) {
        return 0xfe;
    }
    return mLevel;
}


ChipError LightDimmer::OnReport(const DataBlock* block) {
    if (block->path.clusterId != Id) {
        return LightOnOff::OnReport(block);
    }

    const auto newValue = static_cast<uint8_t>(block->data.asInt());
    UpdateLevel(newValue);
    return CHIP_NO_ERROR;
}

ChipError LightDimmer::OnReadAttributes() {
    GetRemoteAttribute(Id, Attributes::CurrentLevel::Id);
    return LightOnOff::OnReadAttributes();
}

Protocols::InteractionModel::Status LightDimmer::ReadAttribute(
    ClusterId clusterId,
    AttributeId attributeId,
    uint8_t* buffer,
    uint16_t maxReadLength) {
    ChipLogProgress(DeviceLayer, "OnOffAttributes: attrId=%d, maxReadLength=%d", attributeId, maxReadLength);
    if (clusterId != Id) {
        return LightOnOff::ReadAttribute(clusterId, attributeId, buffer, maxReadLength);
    }

    ChipLogProgress(DeviceLayer, "ReadAttribute: attrId=%d, maxReadLength=%d", attributeId, maxReadLength);
    if (attributeId == CurrentLevel::Id && (maxReadLength == 1)) {
        *buffer = this->GetLevel();
        ChipLogProgress(DeviceLayer, "Current Level = %d", this->GetLevel());
    } else if ((attributeId == ClusterRevision::Id) && (maxReadLength == 2)) {
        *buffer = kLevelClusterRevision;
    } else {
        return Protocols::InteractionModel::Status::UnsupportedRead;
    }
    return Protocols::InteractionModel::Status::Success;
}

Protocols::InteractionModel::Status LightDimmer::WriteAttribute(
    ClusterId clusterId,
    const EmberAfAttributeMetadata* attributeMetadata,
    uint8_t* buffer) {
    if (clusterId != Id) {
        return LightOnOff::WriteAttribute(clusterId, attributeMetadata, buffer);
    }

    if (attributeMetadata->attributeId == CurrentLevel::Id) {
        this->SetLevel(*buffer);
    } else {
        return Protocols::InteractionModel::Status::UnsupportedWrite;
    }
    return Protocols::InteractionModel::Status::Success;
}

ChipError LightDimmer::AttachToIndex(uint16_t index) {
    ChipError ret = LightOnOff::AttachToIndex(index);
    if (ret == CHIP_NO_ERROR) {
        emberAfLevelControlClusterServerInitCallback(GetEndpoint());
    }
    return ret;
}
